package com.ruoyi.common.wecom.client;

import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.common.wecom.entity.WeComAccessToken;
import com.ruoyi.common.wecom.entity.WeComLoginUserInfo;
import com.ruoyi.common.wecom.entity.WeComReturnMessage;
import com.ruoyi.common.wecom.entity.WeComSendTextMessage;
import com.ruoyi.common.wecom.enums.MessageType;
import com.ruoyi.common.wecom.handlers.DefaultWeComResponseHandler;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.HttpClientBuilder;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.net.URISyntaxException;
import java.rmi.ServerException;
import java.time.Duration;
import java.util.HashMap;

import static com.ruoyi.common.wecom.constants.WeComPropConstants.*;
import static com.ruoyi.common.wecom.constants.WeComUrlConstants.*;

/**
 *
 */
@Component
@Slf4j
public class WeComUtils {

    private HttpClient httpClient;

    public WeComUtils() {
        httpClient = HttpClientBuilder.create().build();
    }

    public WeComAccessToken getAccessToken() throws URISyntaxException, IOException {
//        log.info("WeComUtils::getAccessToken start!");
        // 判断redis里面有没有token,有的话，直接返回
        WeComAccessToken weComAccessToken = RedisUtils.getCacheObject(REDIS_CACHE_KEY_WECOM_TOKEN);
        if (weComAccessToken != null) {
//            log.info("WeComUtils:getAccessToken end, return1:" + weComAccessToken);
            return weComAccessToken;
        }
        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("corpid", APP_ID);
        paramMap.put("corpsecret", CORP_SECRET);
        String respBody = HttpUtil.get(ACCESS_TOKEN_URL, paramMap, 3000);
//        URIBuilder uriBuilder = new URIBuilder(ACCESS_TOKEN_URL);
//        uriBuilder.addParameter("corpid", APP_ID);
//        uriBuilder.addParameter("corpsecret", CORP_SECRET);
//        log.info("WeComUtils::getAccessToken==> respBody:" + respBody);

//        HttpGet httpGet = new HttpGet(uriBuilder.build());
//        weComAccessToken = httpClient.execute(httpGet, new DefaultWeComResponseHandler<>(WeComAccessToken.class));
        weComAccessToken = JSON.parseObject(respBody, WeComAccessToken.class);
        if (weComAccessToken != null){
            // 设置token到redis, 并设置有效期，有效期内直接从redis获取
            RedisUtils.setCacheObject(REDIS_CACHE_KEY_WECOM_TOKEN, weComAccessToken, Duration.ofSeconds(weComAccessToken.getExpiresIn()));
//            log.info("WeComUtils:getAccessToken end, return2:" + weComAccessToken);
            return weComAccessToken;
        }
        throw new ServerException("获取token api 返回null");

    }

    public WeComLoginUserInfo getLoginUserInfo(String accessToken, String authCode) throws IOException, URISyntaxException {
        URIBuilder uriBuilder = new URIBuilder(LOGIN_USER_INFO_URL);
        uriBuilder.addParameter("access_token", accessToken);
        uriBuilder.addParameter("code", authCode);
        HttpGet httpGet = new HttpGet(uriBuilder.build());
        return httpClient.execute(httpGet, new DefaultWeComResponseHandler<>(WeComLoginUserInfo.class));
    }

    /**
     * 发送文本消息
     * @param accessToken
     * @param content
     * @param toUser
     * @param toPart
     * @param toTag
     * @return
     * @throws IOException
     * @throws URISyntaxException
     */
    public WeComReturnMessage sendTextMessage(String accessToken, String content,
                                              String toUser, String toPart, String toTag) throws IOException, URISyntaxException {
        URIBuilder uriBuilder = new URIBuilder(SEND_MESSAGE_URL);
        uriBuilder.addParameter("access_token", accessToken);
        WeComSendTextMessage weComSendTextMessage = new WeComSendTextMessage();
        weComSendTextMessage.setMessageType(MessageType.TEXT);
        weComSendTextMessage.setContent(content);
        weComSendTextMessage.setToUser(toUser);
        weComSendTextMessage.setToParty(toPart);
        weComSendTextMessage.setToTag(toTag);
        String jsonString = JSON.toJSONString(weComSendTextMessage.getParamMap());

        HttpPost httpPost = new HttpPost(uriBuilder.build());
        httpPost.setEntity(new StringEntity(jsonString, "utf-8"));
        return httpClient.execute(httpPost, new DefaultWeComResponseHandler<>(WeComReturnMessage.class));
    }

    public WeComReturnMessage sendTextMessage(String toUser, String title, String processName, String startUserName) {
        WeComAccessToken accessToken = null;
        try {
            accessToken = getAccessToken();
        } catch (Exception e) {
            throw new ServiceException("获取token失败" + e.getMessage());
        }
        if (ObjUtil.isNull(accessToken) || StrUtil.isEmpty(accessToken.getAccessToken())) {
            throw new ServiceException("获取token无效");
        }

        HashMap<String, Object> paramMap = new HashMap<>();
        paramMap.put("touser", toUser);
        paramMap.put("msgtype", "textcard");
        paramMap.put("agentid", AGENT_ID);
        HashMap<String, String> textObj = new HashMap<>();
        textObj.put("title", title);
        textObj.put("description", "<div class=\"highlight\">流程名称：" + processName + "</div>" + "<div class=\"highlight\">发起人：" + startUserName + "</div>");
        textObj.put("url", WECHAT_URL);
        paramMap.put("textcard", textObj);
        paramMap.put("safe", 0);
        paramMap.put("enable_id_trans", 0);
        paramMap.put("enable_duplicate_check", 0);
        log.info("sendTextMessage == paramMap:" + paramMap.toString());
        String respBody = HttpRequest.post(SEND_MESSAGE_URL + "?access_token=" + accessToken.getAccessToken())
            .body(JSONUtil.toJsonStr(paramMap))
            .timeout(5000).execute().body();
        WeComReturnMessage weComReturnMessage = JSON.parseObject(respBody, WeComReturnMessage.class);
        if (weComReturnMessage.getErrcode() != 0) {
            throw new ServiceException(weComReturnMessage.getErrmsg());
        }
        return weComReturnMessage;
    }
}
